
#include <libcoco.h>
#include <concurrent/concurrent.h>
#include <concurrent/shortname.h>

#define CROUT_MALLOC(size)	  __builtin_malloc(size)
#define CROUT_FREE(ptr, size)   __builtin_free(ptr)

typedef struct crout_int{
	// word_t   stk_size;
	void *(*routine)(void*);
	void *arg;
	void *stk_ptr;
	size_t stk_size;
	struct concurrent_ctx co;
}crout_int_t;

static void async_worker(struct concurrent_ctx *ctx){
	crout_int_t * cr = ctx_get_resume_value(ctx);
	// aco_yield();
	cr->routine(cr->arg);
	concurrent_arch_trampoline_to_caller(ctx);
}

/* 全局初始化 */
static __attribute__((constructor)) void concurrent_sysinit(){
	concurrent_init();
}

int 	crout_create( crout_t **pco,const crout_attr_t *attr,void *(*routine)(void*),void *arg){
	void *p = CROUT_MALLOC(sizeof(crout_int_t));
	if (!p) return -1;
	crout_int_t * cr = (crout_int_t *)p;
	
	cr->routine = routine;
	cr->arg = arg;
	cr->stk_size = attr->stack_size;
	cr->stk_ptr = CROUT_MALLOC(cr->stk_size);
	if (!cr->stk_ptr) {
		CROUT_FREE(cr, sizeof(crout_int_t));
		return -1;
	}

	ctx_construct(&cr->co, cr->stk_ptr, cr->stk_size, async_worker, cr);
	*pco = (crout_t *)cr;
	// aco_resume(cr->aco);
	return 0;
}

void	crout_resume( crout_t *co){
	crout_int_t *cr = (crout_int_t *)co;
	// coroutine_resume(cr->S, cr->coid);
	resume_value(&cr->co, cr);
}


void	crout_yield( crout_t *co ){
	crout_int_t *cr = (crout_int_t *)co;
	// coroutine_yield(cr->S);
	// aco_yield();
	yield_value(&cr->co, 0);
}

void	crout_release( crout_t *co ){
	crout_int_t *cr = (crout_int_t *)co;
	// coroutine_close(cr->S);
	ctx_destruct(&cr->co);
	CROUT_FREE(cr->stk_ptr, cr->stk_size);
	CROUT_FREE(cr, sizeof(crout_int_t));
}

void	crout_reset(crout_t * co){
	crout_int_t *cr = (crout_int_t *)co;
	ctx_construct(&cr->co, cr->stk_ptr, cr->stk_size, async_worker, cr);
}
